﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using InterfacesTransformation;
using MyGrouping;
using MyGroupReducing;
using MyDuplicationRemover;
using MyWordSegmentorJSharp;
using System.Reflection;
using System.IO;
using DTO;
using DAL;

namespace TransformationHost
{
    public partial class TransformationHost : UserControl, IHost
    {
        public TransformationHost()
        {
            InitializeComponent();
        }

        #region Webpage Grouping
        public void FeedBack(string feedBackStr, IWebpageGrouping pluginInterface)
        {
            //...
        }

        private Types.AvailableWebpageGroupingCollection availWGPluginList = new Types.AvailableWebpageGroupingCollection();

        public Types.AvailableWebpageGroupingCollection AvailWGPluginList
        {
            get { return availWGPluginList; }
            set { availWGPluginList = value; }
        }

        private void AddWGPlugin(string fileName)
        {
            FileInfo fi = new FileInfo(fileName);
            if (fi.Extension.Equals(".dll"))
            {
                try
                {
                    Assembly pluginAssembly = Assembly.LoadFrom(fileName);

                    foreach (Type pluginType in pluginAssembly.GetTypes())
                    {
                        if (pluginType.IsPublic)
                        {
                            if (!pluginType.IsAbstract)
                            {
                                Type typeInterface = pluginType.GetInterface("InterfacesTransformation.IWebpageGrouping", true);

                                if (typeInterface != null)
                                {
                                    Types.AvailableWebpageGroupingPlugin newPlugin = new Types.AvailableWebpageGroupingPlugin();

                                    newPlugin.MyAssemblyPath = fileName;

                                    newPlugin.MyInstance = (IWebpageGrouping)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));

                                    newPlugin.MyInstance.PluginHost = this;

                                    newPlugin.MyInstance.Initialize();

                                    this.availWGPluginList.Clear(); // Make sure there is just only one plugin at time
                                    this.availWGPluginList.Add(newPlugin);

                                    newPlugin = null;
                                }

                                typeInterface = null;
                            }
                        }
                    }

                    pluginAssembly = null;
                }
                catch
                {
                    MessageBox.Show("Loading plugin dll failed!");
                }
            }
        }

        public void AddWGPlugins(string[] fileNames)
        {
            foreach (string file in fileNames)
            {
                AddWGPlugin(file);
            }

            if (availWGPluginList.Count == 0)
            {
                MessageBox.Show("No plugin was load!");
            }
        }

        public void CloseAllWGPlugin()
        {
            foreach (Types.AvailableWebpageGroupingPlugin plugin in availWGPluginList)
            {
                plugin.MyInstance.PluginDispose();

                plugin.MyInstance = null;
            }

            availWGPluginList.Clear();
        }

        public void FindWGPlugins(string path)
        {
            availWGPluginList.Clear();

            foreach (string file in Directory.GetFiles(path))
            {
                FileInfo fileInfo = new FileInfo(file);

                if (fileInfo.Extension.Equals(".dll"))
                {
                    this.AddWGPlugin(file);
                }
            }
        }

        public void FindWGPlugins()
        {
            FindWGPlugins(AppDomain.CurrentDomain.BaseDirectory);
        }

        public void LoadWGPlugins()
        {
            openFileDialog_LoadPlugin.Multiselect = true;
            openFileDialog_LoadPlugin.ShowDialog();

            if (openFileDialog_LoadPlugin.FileNames.Length != 0)
            {
                string[] selectedFiles = openFileDialog_LoadPlugin.FileNames;

                AddWGPlugins(selectedFiles);
            }
        }
        #endregion

        #region Group Reducing
        public void FeedBack(string feedBackStr, IGroupReducing pluginInterface)
        {
            //...
        }

        private Types.AvailableGroupReducerPluginCollection availGRPluginList = new Types.AvailableGroupReducerPluginCollection();

        public Types.AvailableGroupReducerPluginCollection AvailGRPluginList
        {
            get { return availGRPluginList; }
            set { availGRPluginList = value; }
        }

        private void AddGRPlugin(string fileName)
        {
            FileInfo fi = new FileInfo(fileName);
            if (fi.Extension.Equals(".dll"))
            {
                try
                {
                    Assembly pluginAssembly = Assembly.LoadFrom(fileName);

                    foreach (Type pluginType in pluginAssembly.GetTypes())
                    {
                        if (pluginType.IsPublic)
                        {
                            if (!pluginType.IsAbstract)
                            {
                                Type typeInterface = pluginType.GetInterface("InterfacesTransformation.IGroupReducing", true);

                                if (typeInterface != null)
                                {
                                    Types.AvailableGroupReducerPlugin newPlugin = new Types.AvailableGroupReducerPlugin();

                                    newPlugin.MyAssemblyPath = fileName;

                                    newPlugin.MyInstance = (IGroupReducing)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));

                                    newPlugin.MyInstance.PluginHost = this;

                                    newPlugin.MyInstance.Initialize();

                                    this.availGRPluginList.Clear(); // Make sure there is just only one plugin at time
                                    this.availGRPluginList.Add(newPlugin);

                                    newPlugin = null;
                                }

                                typeInterface = null;
                            }
                        }
                    }

                    pluginAssembly = null;
                }
                catch
                {
                    MessageBox.Show("Loading plugin dll failed!");
                }
            }
        }

        public void AddGRPlugins(string[] fileNames)
        {
            foreach (string file in fileNames)
            {
                AddGRPlugin(file);
            }

            if (availGRPluginList.Count == 0)
            {
                MessageBox.Show("No plugin was load!");
            }
        }

        public void CloseAllGRPlugin()
        {
            foreach (Types.AvailableGroupReducerPlugin plugin in availGRPluginList)
            {
                plugin.MyInstance.PluginDispose();

                plugin.MyInstance = null;
            }

            availGRPluginList.Clear();
        }

        public void FindGRPlugins(string path)
        {
            availGRPluginList.Clear();

            foreach (string file in Directory.GetFiles(path))
            {
                FileInfo fileInfo = new FileInfo(file);

                if (fileInfo.Extension.Equals(".dll"))
                {
                    this.AddGRPlugin(file);
                }
            }
        }

        public void FindGRPlugins()
        {
            FindGRPlugins(AppDomain.CurrentDomain.BaseDirectory);
        }

        public void LoadGRPlugins()
        {
            openFileDialog_LoadPlugin.Multiselect = true;
            openFileDialog_LoadPlugin.ShowDialog();

            if (openFileDialog_LoadPlugin.FileNames.Length != 0)
            {
                string[] selectedFiles = openFileDialog_LoadPlugin.FileNames;

                AddGRPlugins(selectedFiles);
            }
        }
        #endregion
        
        #region Duplication Remover
        public void FeedBack(string feedBackStr, IDuplicationRemover pluginInterface)
        {
            //...
        }

        private Types.AvailableDuplicationRemoverPluginCollection availDRPluginList = new Types.AvailableDuplicationRemoverPluginCollection();

        public Types.AvailableDuplicationRemoverPluginCollection AvailDRPluginList
        {
            get { return availDRPluginList; }
            set { availDRPluginList = value; }
        }

        private void AddDRPlugin(string fileName)
        {
            FileInfo fi = new FileInfo(fileName);
            if (fi.Extension.Equals(".dll"))
            {
                try
                {
                    Assembly pluginAssembly = Assembly.LoadFrom(fileName);

                    foreach (Type pluginType in pluginAssembly.GetTypes())
                    {
                        if (pluginType.IsPublic)
                        {
                            if (!pluginType.IsAbstract)
                            {
                                Type typeInterface = pluginType.GetInterface("InterfacesTransformation.IDuplicationRemover", true);

                                if (typeInterface != null)
                                {
                                    Types.AvailableDuplicationRemoverPlugin newPlugin = new Types.AvailableDuplicationRemoverPlugin();

                                    newPlugin.MyAssemblyPath = fileName;

                                    newPlugin.MyInstance = (IDuplicationRemover)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));

                                    newPlugin.MyInstance.PluginHost = this;

                                    newPlugin.MyInstance.Initialize();

                                    this.availDRPluginList.Clear(); // Make sure there is just only one plugin at time
                                    this.availDRPluginList.Add(newPlugin);

                                    newPlugin = null;
                                }

                                typeInterface = null;
                            }
                        }
                    }

                    pluginAssembly = null;
                }
                catch
                {
                    MessageBox.Show("Loading plugin dll failed!");
                }
            }
        }

        public void AddDRPlugins(string[] fileNames)
        {
            foreach (string file in fileNames)
            {
                AddDRPlugin(file);
            }

            if (availDRPluginList.Count == 0)
            {
                MessageBox.Show("No plugin was load!");
            }
        }

        public void CloseAllDRPlugin()
        {
            foreach (Types.AvailableDuplicationRemoverPlugin plugin in availDRPluginList)
            {
                plugin.MyInstance.PluginDispose();

                plugin.MyInstance = null;
            }

            availDRPluginList.Clear();
        }

        public void FindDRPlugins(string path)
        {
            availDRPluginList.Clear();

            foreach (string file in Directory.GetFiles(path))
            {
                FileInfo fileInfo = new FileInfo(file);

                if (fileInfo.Extension.Equals(".dll"))
                {
                    this.AddDRPlugin(file);
                }
            }
        }

        public void FindDRPlugins()
        {
            FindDRPlugins(AppDomain.CurrentDomain.BaseDirectory);
        }

        public void LoadDRPlugins()
        {
            openFileDialog_LoadPlugin.Multiselect = false;
            openFileDialog_LoadPlugin.ShowDialog();

            if (openFileDialog_LoadPlugin.FileName != string.Empty)
            {
                string selectedFile = openFileDialog_LoadPlugin.FileName;

                this.availDRPluginList.Clear();
                AddDRPlugin(selectedFile);
            }
        }
        #endregion

        #region Word Segmentor
        public void FeedBack(string feedBackStr, IWordSegmentor pluginInterface)
        {
            //...
        }

        private Types.AvailableWordSegmentorPluginCollection availWSgPluginList = new Types.AvailableWordSegmentorPluginCollection();

        public Types.AvailableWordSegmentorPluginCollection AvailWSgPluginList
        {
            get { return availWSgPluginList; }
            set { availWSgPluginList = value; }
        }

        private void AddWSgPlugin(string fileName)
        {
            FileInfo fi = new FileInfo(fileName);
            if (fi.Extension.Equals(".dll"))
            {
                try
                {
                    Assembly pluginAssembly = Assembly.LoadFrom(fileName);

                    foreach (Type pluginType in pluginAssembly.GetTypes())
                    {
                        if (pluginType.IsPublic)
                        {
                            if (!pluginType.IsAbstract)
                            {
                                Type typeInterface = pluginType.GetInterface("InterfacesTransformation.IWordSegmentor", true);

                                if (typeInterface != null)
                                {
                                    Types.AvailableWordSegmentorPlugin newPlugin = new Types.AvailableWordSegmentorPlugin();

                                    newPlugin.MyAssemblyPath = fileName;

                                    newPlugin.MyInstance = (IWordSegmentor)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));

                                    newPlugin.MyInstance.PluginHost = this;

                                    newPlugin.MyInstance.Initialize();

                                    this.availWSgPluginList.Clear(); // Make sure there is just only one plugin at time
                                    this.availWSgPluginList.Add(newPlugin);

                                    newPlugin = null;
                                }

                                typeInterface = null;
                            }
                        }
                    }

                    pluginAssembly = null;
                }
                catch
                {
                    MessageBox.Show("Loading plugin dll failed!");
                }
            }
        }

        public void AddWSgPlugins(string[] fileNames)
        {
            foreach (string file in fileNames)
            {
                AddWSgPlugin(file);
            }

            if (availWSgPluginList.Count == 0)
            {
                MessageBox.Show("No plugin was load!");
            }
        }

        public void CloseAllWSgPlugin()
        {
            foreach (Types.AvailableWordSegmentorPlugin plugin in availWSgPluginList)
            {
                plugin.MyInstance.PluginDispose();

                plugin.MyInstance = null;
            }

            availWSgPluginList.Clear();
        }

        public void FindWSgPlugins(string path)
        {
            availWSgPluginList.Clear();

            foreach (string file in Directory.GetFiles(path))
            {
                FileInfo fileInfo = new FileInfo(file);

                if (fileInfo.Extension.Equals(".dll"))
                {
                    this.AddWSgPlugin(file);
                }
            }
        }

        public void FindWSgPlugins()
        {
            FindWSgPlugins(AppDomain.CurrentDomain.BaseDirectory);
        }

        public void LoadWSgPlugins()
        {
            openFileDialog_LoadPlugin.Multiselect = false;
            openFileDialog_LoadPlugin.ShowDialog();

            if (openFileDialog_LoadPlugin.FileName != string.Empty)
            {
                string selectedFile = openFileDialog_LoadPlugin.FileName;

                this.availWSgPluginList.Clear();
                AddWSgPlugin(selectedFile);
            }
        }
        #endregion

        #region Webpage Group Functions
        public List<List<int>> Grouping()
        {
            if (this.availWGPluginList.Count != 0)
            {
                try
                {
                    return availWGPluginList.Get(0).MyInstance.Grouping();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            else
            {
                throw new Exception("Webpage Grouping Plugin is not loaded!");
            }
        }
        #endregion

        #region Group Reducing Functions
        public List<List<int>> GroupReducing(List<List<int>> groups)
        {
            if (this.availGRPluginList.Count != 0)
            {
                try
                {
                    return availGRPluginList.Get(0).MyInstance.Reducing(groups);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            else
            {
                throw new Exception("Webpage Groups Reducing Plugin is not loaded!");
            }
        }
        #endregion

        #region Duplication Removing Functions
        public void RemoveDuplication(List<Webpage> curGroup)
        {
            if (this.availDRPluginList.Count != 0)
            {
                try
                {
                    availDRPluginList.Get(0).MyInstance.RemoveDuplication(curGroup);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            else
            {
                throw new Exception("Duplication Removing Plugin is not loaded!");
            }
        }
        #endregion

        #region Word Segmentor Functions
        public string SegmentString(string inputStr)
        {
            if (this.availWSgPluginList.Count != 0)
            {
                try
                {
                    return availWSgPluginList.Get(0).MyInstance.Segment(inputStr);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            else
            {
                throw new Exception("Word Segmentor Plugin is not loaded!");
            }
        }
        #endregion

        #region Fixed Functions
        /// <summary>
        /// Insert pages into database by groups
        /// </summary>
        /// <param name="LocalRepositoryPath">The physical path </param>
        /// <param name="Groups">Groups of pages</param>
        public void InsertGroup(string LocalRepositoryPath, List<int> curGroup)
        {
            List<Webpage> listWebpageGroup = new List<Webpage>();
            listWebpageGroup = ConvertToWebpageObjectGroup(LocalRepositoryPath, curGroup);
            RemoveDuplication(listWebpageGroup);
            foreach (Webpage i in listWebpageGroup)
            {
                InsertWebpage(i);
            }
        }

        private List<Webpage> ConvertToWebpageObjectGroup(string LocalRepositoryPath, List<int> curGroup)
        {
            List<Webpage> listWebpageGroup = new List<Webpage>();
            Webpage curWebpage = new Webpage();
            foreach (int curWebpageID in curGroup)
            {
                List<Webpage> webpageList = new List<Webpage>();
                try
                {
                    webpageList = WebpageDAL.GetWebpagesRange(curWebpageID, curWebpageID);
                }
                catch (Exception)
                {
                    throw new Exception("Database error");
                }

                try
                {
                    curWebpage = Webpage.HTMLWebpage2MyWebPage(LocalRepositoryPath + "\\" + webpageList[0].Path);
                    curWebpage.WebtagTree = BuildWebtagTreeFromLeavesXPath(curWebpage.TextTagList, curWebpageID);
                    curWebpage.ID = curWebpageID;
                    listWebpageGroup.Add(curWebpage);
                }
                catch (Exception)
                {
                    // this page is empty
                    WebpageDAL.DeleteEmptyWebpage(curWebpageID);
                }
            }

            return listWebpageGroup;
        }

        private void InsertWebpage(Webpage curWebpage)
        {
            try
            {
                WebpageDAL.UpdateWebpage(curWebpage.Title, curWebpage.ID);
                InsertTags(curWebpage.OutgoingLinks, curWebpage.TextTagList, curWebpage.ID);
                InsertTitleTerms(curWebpage.Title, curWebpage.ID);
                foreach (string i in curWebpage.MetaKeywords)
                {
                    WebpageDAL.InsertMetaKeyword(i, curWebpage.ID);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Insert terms received from webpage title to database.
        /// </summary>
        
        private void InsertTitleTerms(string Title, int webpageID)
        {
            string segmentedTitle = SegmentString(Title);
            
            char[] unwantedChars = new char[] { '-', '.', ';', '!', ':', ',', '(', ')', '[', ']', '{', '}', '\\', '/', '\'', '<', '>' };

            segmentedTitle = Utilities.StringLib.ProcessString.ReplaceUnwantedChars(segmentedTitle, " ", unwantedChars);
            string[] splitedWords = Utilities.StringLib.ProcessString.ProcessSplitText(segmentedTitle);
            foreach (string curWord in splitedWords)
            {
                WebpageDAL.InsertTitleKeyword(curWord, webpageID);
            }
        }

        private Webtag BuildWebtagTreeFromLeavesXPath(List<Webtag> webtagList, int webpageID)
        {
            Webtag virtualRootWebtag = new Webtag();
            virtualRootWebtag.Name = "Virtual Root";
            virtualRootWebtag.WebpageID = webpageID;
            for (int i = 0; i < webtagList.Count; i++)
            {
                AddXPathToWebtagTree(virtualRootWebtag, webtagList[i].XPath, webtagList[i].Text, webtagList[i].ID, webpageID, webtagList[i].XPath);
            }

            return virtualRootWebtag;
        }

        private void AddXPathToWebtagTree(Webtag curWebtag, string curPath, string leafText, int leafId, int webpageID, string originalXPath)
        {
            if ((curPath.Length == 0) || (curPath[0] != '/'))
            {
                return;
            }
            else
            {
                int endTagNameIndex = curPath.IndexOf('[', 1);
                string tagName = curPath.Substring(1, endTagNameIndex - 1);

                int endTagPosIndex = curPath.IndexOf(']', endTagNameIndex);
                int tagPos = int.Parse(curPath.Substring(endTagNameIndex + 1, endTagPosIndex - endTagNameIndex - 1));

                int count = 1;
                bool isFound = false;

                string remainXPath;
                try
                {
                    remainXPath = curPath.Substring(endTagPosIndex + 1);
                }
                catch
                {
                    remainXPath = string.Empty;
                }

                if (remainXPath == string.Empty)
                {
                    Webtag leafChild = new Webtag(tagName, leafText, originalXPath, string.Empty);
                    leafChild.ID = leafId;
                    leafChild.Parent = curWebtag;
                    leafChild.WebpageID = webpageID;
                    curWebtag.Children.Add(leafChild);
                    return;
                }
                else
                {
                    for (int i = 0; i < curWebtag.Children.Count; i++)
                    {
                        if (curWebtag.Children[i].Name == tagName)
                        {
                            if (count == tagPos)
                            {
                                isFound = true;
                                AddXPathToWebtagTree(curWebtag.Children[i], remainXPath, leafText, leafId, webpageID, originalXPath);
                            }
                            else
                            {
                                count++;
                            }
                        }
                    }

                    if (isFound == false)
                    {
                        Webtag newChild = new Webtag(tagName, string.Empty, string.Empty, string.Empty);
                        newChild.Parent = curWebtag;
                        newChild.WebpageID = webpageID;
                        curWebtag.Children.Add(newChild);
                        AddXPathToWebtagTree(curWebtag.Children[curWebtag.Children.Count - 1], remainXPath, leafText, leafId, webpageID, originalXPath);
                    }
                }
            }
        }

        private void InsertTags(Dictionary<string, Link> linkList, List<Webtag> leafTagList, int WebpageID)
        {
            foreach (Webtag i in leafTagList)
            {
                int tagID = WebtagDAL.InsertTag(i, WebpageID);
                if (linkList.ContainsKey(i.XPath))
                {
                    Link curLink = linkList[i.XPath];
                    WebpageDAL.InsertLink(WebpageID, WebpageDAL.GetWebpageID(curLink.DestURL), curLink.Text, tagID);
                }
            }
        }
        #endregion

        #region GUI Event Handlers
        private void buttonBrowseGroupingPlugin_Click(object sender, EventArgs e)
        {
            openFileDialog_LoadPlugin.Multiselect = false;
            openFileDialog_LoadPlugin.FileName = string.Empty;
            openFileDialog_LoadPlugin.Filter = "Plugin (*.dll) |*.dll";
            if (openFileDialog_LoadPlugin.ShowDialog() == DialogResult.OK)
            {
                this.AddWGPlugins(openFileDialog_LoadPlugin.FileNames);

                if (availWGPluginList.Count != 0)
                {
                    this.textBoxGroupingPluginPath.Text = availWGPluginList.Get(0).MyInstance.PluginName;
                    try
                    {
                        Global.groups = Grouping();
                        List<Webpage> allWebpages = WebpageDAL.GetWebpagesNoChecking();
                        Dictionary<int, Webpage> allWebpagesDict = WebpagesToDict(allWebpages);
                        int count = 1;
                        this.treeViewGroups.Nodes.Clear();
                        foreach (List<int> curGroup in Global.groups)
                        {
                            TreeNode curTreeNode = new TreeNode("Group " + count++ + " (" + curGroup.Count + " webpage(s))");
                            foreach (int curWebpage in curGroup)
                            {
                                Webpage tempWebpage = allWebpagesDict[curWebpage];
                                TreeNode curWebpageNode = new TreeNode("[" + curWebpage + "] [ " + tempWebpage.URL + " ]");
                                curTreeNode.Nodes.Add(curWebpageNode);
                            }
                            this.treeViewGroups.Nodes.Add(curTreeNode);
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

        private Dictionary<int, Webpage> WebpagesToDict(List<Webpage> allWebpages)
        {
            Dictionary<int, Webpage> allWebpagesDict = new Dictionary<int, Webpage>();

            foreach (Webpage curWebpage in allWebpages)
            {
                allWebpagesDict.Add(curWebpage.ID, curWebpage);
            }

            return allWebpagesDict;
        }

        private void buttonRefineGroupPluginBrowse_Click(object sender, EventArgs e)
        {
            openFileDialog_LoadPlugin.Multiselect = false;
            openFileDialog_LoadPlugin.FileName = string.Empty;
            openFileDialog_LoadPlugin.Filter = "Plugin (*.dll) |*.dll";
            if (openFileDialog_LoadPlugin.ShowDialog() == DialogResult.OK)
            {
                this.AddGRPlugins(openFileDialog_LoadPlugin.FileNames);

                if (availGRPluginList.Count != 0)
                {
                    this.textBoxGroupReducingPluginPath.Text = availGRPluginList.Get(0).MyInstance.PluginName;
                    this.groupBoxRefineGroupPluginParameters.Controls.Clear();
                    availGRPluginList.Get(0).MyInstance.PluginUserControl.Dock = DockStyle.Fill;
                    this.groupBoxRefineGroupPluginParameters.Controls.Add(availGRPluginList.Get(0).MyInstance.PluginUserControl);
                }
            }
        }

        private void buttonDuplicationRemoverPluginBrowse_Click(object sender, EventArgs e)
        {
            openFileDialog_LoadPlugin.Multiselect = false;
            openFileDialog_LoadPlugin.FileName = string.Empty;
            openFileDialog_LoadPlugin.Filter = "Plugin (*.dll) |*.dll";
            if (openFileDialog_LoadPlugin.ShowDialog() == DialogResult.OK)
            {
                this.AddDRPlugins(openFileDialog_LoadPlugin.FileNames);

                if (availDRPluginList.Count != 0)
                {
                    this.textBoxDuplicationRemoverPluginPath.Text = availDRPluginList.Get(0).MyInstance.PluginName;
                    this.groupBoxDuplicationRemoverPluginParameters.Controls.Clear();
                    availDRPluginList.Get(0).MyInstance.PluginUserControl.Dock = DockStyle.Fill;
                    this.groupBoxDuplicationRemoverPluginParameters.Controls.Add(availDRPluginList.Get(0).MyInstance.PluginUserControl);
                }
            }
        }

        private void buttonWordSegmentorBrowse_Click(object sender, EventArgs e)
        {
            openFileDialog_LoadPlugin.Multiselect = false;
            openFileDialog_LoadPlugin.FileName = string.Empty;
            openFileDialog_LoadPlugin.Filter = "Plugin (*.dll) |*.dll";
            if (openFileDialog_LoadPlugin.ShowDialog() == DialogResult.OK)
            {
                this.AddWSgPlugins(openFileDialog_LoadPlugin.FileNames);

                if (availWSgPluginList.Count != 0)
                {
                    this.textBoxWordSegmentroPluginPath.Text = availWSgPluginList.Get(0).MyInstance.PluginName;
                    this.groupBoxWordSegmentorParameters.Controls.Clear();
                    availWSgPluginList.Get(0).MyInstance.PluginUserControl.Dock = DockStyle.Fill;
                    this.groupBoxWordSegmentorParameters.Controls.Add(availWSgPluginList.Get(0).MyInstance.PluginUserControl);
                }
            }
        }

        private void buttonTransformationPhaseRun_Click(object sender, EventArgs e)
        {
            List<List<int>> reducedGroups = new List<List<int>>();

            #region Plugins Loaded Checking
            if (availDRPluginList.Count == 0)
            {
                MessageBox.Show("Duplication Remover Plugin is not loaded");
                return;
            }
            if (availGRPluginList.Count == 0)
            {
                MessageBox.Show("Group Refinement Plugin is not loaded");
                reducedGroups = Global.groups;
            }
            else
            {
                reducedGroups = this.availGRPluginList.Get(0).MyInstance.Reducing(Global.groups);
            }

            if (availWGPluginList.Count == 0)
            {
                MessageBox.Show("Webpages Grouping Plugin is not loaded");
                return;
            }
            if (availWSgPluginList.Count == 0)
            {
                MessageBox.Show("Word Segmentor Plugin is not loaded");
                return;
            }
            #endregion


            int count = 1;
            try
            {
                this.buttonTransformationPhaseRun.Enabled = false;
                
                foreach (List<int> curGroup in reducedGroups)
                {
                    InsertGroup(Global.LocalRepositoryPath, curGroup);
                    labelGroupStatus.Text = string.Empty;
                    labelGroupStatus.Text = "Handle group " + count++ + " /" + reducedGroups.Count;
                }
                
                this.buttonTransformationPhaseRun.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void buttonExport2XML_Click(object sender, EventArgs e)
        {

        } 
        #endregion
    }


    namespace Types
    {
        #region Grouping Types
        public class AvailableWebpageGroupingPlugin
        {
            private IWebpageGrouping myInstance = null;

            public IWebpageGrouping MyInstance
            {
                get { return myInstance; }
                set { myInstance = value; }
            }

            private string myAssemblyPath = string.Empty;

            public string MyAssemblyPath
            {
                get { return myAssemblyPath; }
                set { myAssemblyPath = value; }
            }

        }

        public class AvailableWebpageGroupingCollection : System.Collections.CollectionBase
        {
            public void Add(Types.AvailableWebpageGroupingPlugin plugin)
            {
                this.List.Add(plugin);
            }

            public void Remove(Types.AvailableWebpageGroupingPlugin plugin)
            {
                this.List.Remove(plugin);
            }

            public AvailableWebpageGroupingPlugin Get(int idx)
            {
                try
                {
                    return (AvailableWebpageGroupingPlugin)this.List[idx];
                }
                catch (IndexOutOfRangeException indexOutOfRangeEx)
                {
                    throw indexOutOfRangeEx;
                }
            }

            public AvailableWebpageGroupingPlugin Find(string pluginNameOrPath)
            {
                AvailableWebpageGroupingPlugin result = null;
                foreach (AvailableWebpageGroupingPlugin plugin in this.List)
                {
                    if ((plugin.MyInstance.PluginName.Equals(pluginNameOrPath))
                        || (plugin.MyAssemblyPath.Equals(pluginNameOrPath)))
                    {
                        result = plugin;
                        break;
                    }
                }

                return result;
            }
        }
        #endregion

        #region Group Reducer Types
        public class AvailableGroupReducerPlugin
        {
            private IGroupReducing myInstance = null;

            public IGroupReducing MyInstance
            {
                get { return myInstance; }
                set { myInstance = value; }
            }

            private string myAssemblyPath = string.Empty;

            public string MyAssemblyPath
            {
                get { return myAssemblyPath; }
                set { myAssemblyPath = value; }
            }

        }

        public class AvailableGroupReducerPluginCollection : System.Collections.CollectionBase
        {
            public void Add(Types.AvailableGroupReducerPlugin plugin)
            {
                this.List.Add(plugin);
            }

            public void Remove(Types.AvailableGroupReducerPlugin plugin)
            {
                this.List.Remove(plugin);
            }

            public AvailableGroupReducerPlugin Get(int idx)
            {
                try
                {
                    return (AvailableGroupReducerPlugin)this.List[idx];
                }
                catch (IndexOutOfRangeException indexOutOfRangeEx)
                {
                    throw indexOutOfRangeEx;
                }
            }

            public AvailableGroupReducerPlugin Find(string pluginNameOrPath)
            {
                AvailableGroupReducerPlugin result = null;
                foreach (AvailableGroupReducerPlugin plugin in this.List)
                {
                    if ((plugin.MyInstance.PluginName.Equals(pluginNameOrPath))
                        || (plugin.MyAssemblyPath.Equals(pluginNameOrPath)))
                    {
                        result = plugin;
                        break;
                    }
                }

                return result;
            }
        }
        #endregion

        #region Duplication Remover Types
        public class AvailableDuplicationRemoverPlugin
        {
            private IDuplicationRemover myInstance = null;

            public IDuplicationRemover MyInstance
            {
                get { return myInstance; }
                set { myInstance = value; }
            }

            private string myAssemblyPath = string.Empty;

            public string MyAssemblyPath
            {
                get { return myAssemblyPath; }
                set { myAssemblyPath = value; }
            }

        }

        public class AvailableDuplicationRemoverPluginCollection : System.Collections.CollectionBase
        {
            public void Add(Types.AvailableDuplicationRemoverPlugin plugin)
            {
                this.List.Add(plugin);
            }

            public void Remove(Types.AvailableDuplicationRemoverPlugin plugin)
            {
                this.List.Remove(plugin);
            }

            public AvailableDuplicationRemoverPlugin Get(int idx)
            {
                try
                {
                    return (AvailableDuplicationRemoverPlugin)this.List[idx];
                }
                catch (IndexOutOfRangeException indexOutOfRangeEx)
                {
                    throw indexOutOfRangeEx;
                }
            }

            public AvailableDuplicationRemoverPlugin Find(string pluginNameOrPath)
            {
                AvailableDuplicationRemoverPlugin result = null;
                foreach (AvailableDuplicationRemoverPlugin plugin in this.List)
                {
                    if ((plugin.MyInstance.PluginName.Equals(pluginNameOrPath))
                        || (plugin.MyAssemblyPath.Equals(pluginNameOrPath)))
                    {
                        result = plugin;
                        break;
                    }
                }

                return result;
            }
        }
        #endregion

        #region Word Segmentor Types
        public class AvailableWordSegmentorPlugin
        {
            private IWordSegmentor myInstance = null;

            public IWordSegmentor MyInstance
            {
                get { return myInstance; }
                set { myInstance = value; }
            }

            private string myAssemblyPath = string.Empty;

            public string MyAssemblyPath
            {
                get { return myAssemblyPath; }
                set { myAssemblyPath = value; }
            }

        }

        public class AvailableWordSegmentorPluginCollection : System.Collections.CollectionBase
        {
            public void Add(Types.AvailableWordSegmentorPlugin plugin)
            {
                this.List.Add(plugin);
            }

            public void Remove(Types.AvailableWordSegmentorPlugin plugin)
            {
                this.List.Remove(plugin);
            }

            public AvailableWordSegmentorPlugin Get(int idx)
            {
                try
                {
                    return (AvailableWordSegmentorPlugin)this.List[idx];
                }
                catch (IndexOutOfRangeException indexOutOfRangeEx)
                {
                    throw indexOutOfRangeEx;
                }
            }

            public AvailableWordSegmentorPlugin Find(string pluginNameOrPath)
            {
                AvailableWordSegmentorPlugin result = null;
                foreach (AvailableWordSegmentorPlugin plugin in this.List)
                {
                    if ((plugin.MyInstance.PluginName.Equals(pluginNameOrPath))
                        || (plugin.MyAssemblyPath.Equals(pluginNameOrPath)))
                    {
                        result = plugin;
                        break;
                    }
                }

                return result;
            }
        }
        #endregion
    }
}
